[IA64] fix a fetch code bug
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 9 Aug 2006 14:01:52 +0000 (08:01 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Wed, 9 Aug 2006 14:01:52 +0000 (08:01 -0600)
Fetch code may fail, if there is no corresponding tlb entry
in THASH-VTLB. This patch adds "retry mechanism" to resolve
this issue.

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
xen/arch/ia64/vmx/mmio.c
xen/arch/ia64/vmx/vmmu.c
xen/arch/ia64/vmx/vmx_virt.c
xen/arch/ia64/xen/faults.c
xen/include/asm-ia64/bundle.h
xen/include/asm-ia64/vmmu.h

index 1e4f3402b0af8541b57b414c83f9c6a528e3940b..c1de4a786ff994175243cb830689ae6bd12fe433 100644 (file)
@@ -433,7 +433,10 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
     u64 data, value,post_update, slot1a, slot1b, temp;
     INST64 inst;
     regs=vcpu_regs(vcpu);
-    bundle = __vmx_get_domain_bundle(regs->cr_iip);
+    if (IA64_RETRY == __vmx_get_domain_bundle(regs->cr_iip, &bundle)) {
+        /* if fetch code fail, return and try again */
+        return;
+    }
     slot = ((struct ia64_psr *)&(regs->cr_ipsr))->ri;
     if (!slot) inst.inst = bundle.slot0;
     else if (slot == 1){
index 876438a3996f30d6140bf8cf064fbf1c3d8a08d3..4bff1727ea27b401c02c961eaf305adb466f595a 100644 (file)
@@ -305,13 +305,13 @@ int unimplemented_gva(VCPU *vcpu,u64 vadr)
 
 
 /*
- * Prefetch guest bundle code.
+ * Fetch guest bundle code.
  * INPUT:
- *  code: buffer pointer to hold the read data.
- *  num:  number of dword (8byts) to read.
+ *  gip: guest ip
+ *  pbundle: used to return fetched bundle.
  */
-int
-fetch_code(VCPU *vcpu, u64 gip, u64 *code1, u64 *code2)
+unsigned long
+fetch_code(VCPU *vcpu, u64 gip, IA64_BUNDLE *pbundle)
 {
     u64     gpip=0;   // guest physical IP
     u64     *vpa;
@@ -336,8 +336,10 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *code1, u64 *code2)
         maddr = (mfn << PAGE_SHIFT) | (gpip & (PAGE_SIZE - 1));
     }else{
         tlb = vhpt_lookup(gip);
-        if( tlb == NULL)
-            panic_domain(vcpu_regs(vcpu),"No entry found in ITLB and DTLB\n");
+        if (tlb == NULL) {
+            ia64_ptcl(gip, ARCH_PAGE_SHIFT << 2);
+            return IA64_RETRY;
+        }
         mfn = tlb->ppn >> (PAGE_SHIFT - ARCH_PAGE_SHIFT);
         maddr = (tlb->ppn >> (tlb->ps - 12) << tlb->ps) |
                 (gip & (PSIZE(tlb->ps) - 1));
@@ -354,10 +356,10 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *code1, u64 *code2)
     }
     vpa = (u64 *)__va(maddr);
 
-    *code1 = *vpa++;
-    *code2 = *vpa;
+    pbundle->i64[0] = *vpa++;
+    pbundle->i64[1] = *vpa;
     put_page(page);
-    return 1;
+    return IA64_NO_FAULT;
 }
 
 IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
index b34d48f0557ddeba5b5c2357cefe4d044d813e9a..2fcfcf5bc8c17e21d92edd17c077033cb02a6904 100644 (file)
@@ -1334,11 +1334,10 @@ IA64FAULT vmx_emul_mov_from_cr(VCPU *vcpu, INST64 inst)
 
 //#define  BYPASS_VMAL_OPCODE
 extern IA64_SLOT_TYPE  slot_types[0x20][3];
-IA64_BUNDLE __vmx_get_domain_bundle(u64 iip)
+unsigned long
+__vmx_get_domain_bundle(u64 iip, IA64_BUNDLE *pbundle)
 {
-       IA64_BUNDLE bundle;
-       fetch_code( current, iip, &bundle.i64[0], &bundle.i64[1]);
-       return bundle;
+       return fetch_code(current, iip, pbundle);
 }
 
 /** Emulate a privileged operation.
index ee25ab96b43ecdecd5c4953ab2f4de389543a54f..a37dfc8c80b632a7fb8a85b03f5ed6bf717a114b 100644 (file)
@@ -323,8 +323,10 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
        if (!fp_fault && (ia64_psr(regs)->ri == 0))
                fault_ip -= 16;
 
-       if (VMX_DOMAIN(current))
-               bundle = __vmx_get_domain_bundle(fault_ip);
+       if (VMX_DOMAIN(current)) {
+               if (IA64_RETRY == __vmx_get_domain_bundle(fault_ip, &bundle))
+                       return IA64_RETRY;
+       }
        else 
                bundle = __get_domain_bundle(fault_ip);
 
@@ -555,6 +557,7 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i
        struct vcpu *v = current;
        unsigned long check_lazy_cover = 0;
        unsigned long psr = regs->cr_ipsr;
+       unsigned long status;
 
        /* Following faults shouldn'g be seen from Xen itself */
        BUG_ON (!(psr & IA64_PSR_CPL));
@@ -615,14 +618,23 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i
                // FIXME: Should we handle unaligned refs in Xen??
                vector = IA64_UNALIGNED_REF_VECTOR; break;
            case 32:
-               if (!(handle_fpu_swa(1, regs, isr))) {
+               status = handle_fpu_swa(1, regs, isr);
+               if (!status) {
                    vcpu_increment_iip(v);
                    return;
                }
+               // fetch code fail
+               if (IA64_RETRY == status)
+                       return;
                printf("ia64_handle_reflection: handling FP fault\n");
                vector = IA64_FP_FAULT_VECTOR; break;
            case 33:
-               if (!(handle_fpu_swa(0, regs, isr))) return;
+               status = handle_fpu_swa(0, regs, isr);
+               if (!status)
+                       return;
+               // fetch code fail
+               if (IA64_RETRY == status)
+                       return;
                printf("ia64_handle_reflection: handling FP trap\n");
                vector = IA64_FP_TRAP_VECTOR; break;
            case 34:
index a2e44a4852978007cffb0e78dbb0329f6b881bed..7a1b11e9f325f6e8f78f87da0138c655e2eb0788 100644 (file)
@@ -223,7 +223,7 @@ typedef union U_INST64 {
     INST64_M47 M47;    // purge translation entry
 } INST64;
 
-extern IA64_BUNDLE __vmx_get_domain_bundle(unsigned long iip);
+extern unsigned long __vmx_get_domain_bundle(unsigned long iip, IA64_BUNDLE *pbundle);
 extern IA64_BUNDLE __get_domain_bundle(unsigned long iip);
 
 #define MASK_41 ((unsigned long)0x1ffffffffff)
index 0f6d00a5bfed88705ed838a39397fbb206514476..ccd1ed509931ca1d8a3199ab5a4ab11565479162 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/tlb.h>
 #include <asm/regionreg.h>
 #include <asm/vmx_mm_def.h>
+#include <asm/bundle.h>
 //#define         THASH_TLB_TR            0
 //#define         THASH_TLB_TC            1
 
@@ -299,7 +300,7 @@ extern void free_domain_tlb(struct vcpu *v);
 extern thash_data_t * vsa_thash(PTA vpta, u64 va, u64 vrr, u64 *tag);
 extern thash_data_t * vhpt_lookup(u64 va);
 extern void machine_tlb_purge(u64 va, u64 ps);
-extern int fetch_code(struct vcpu *vcpu, u64 gip, u64 *code1, u64 *code2);
+extern unsigned long fetch_code(struct vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle);
 extern void emulate_io_inst(struct vcpu *vcpu, u64 padr, u64 ma);
 extern int vhpt_enabled(struct vcpu *vcpu, uint64_t vadr, vhpt_ref_t ref);
 extern void vtlb_insert(struct vcpu *vcpu, u64 pte, u64 itir, u64 va);